package my.graduation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.jsonwebtoken.Claims;
import my.graduation.constant.JwtClaimsConstant;
import my.graduation.dto.DoctorInfoDto;
import my.graduation.dto.EmployeeLoginDto;
import my.graduation.dto.EmployeeLogoutDto;
import my.graduation.dto.RepassDto;
import my.graduation.entity.Administrator;
import my.graduation.entity.Clinic;
import my.graduation.entity.Department;
import my.graduation.entity.Doctor;
import my.graduation.enums.HttpCodeEnums;
import my.graduation.mapper.ClinicMapper;
import my.graduation.mapper.DepartmentMapper;
import my.graduation.mapper.DoctorMapper;
import my.graduation.properties.JwtProperties;
import my.graduation.result.Result;
import my.graduation.service.DoctorService;
import my.graduation.util.JwtUtil;
import my.graduation.vo.AdminVO;
import my.graduation.vo.DoctorLoginVO;
import my.graduation.vo.DoctorVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author: RavenLyn
 * @Date: 2024-11-27
 */
@Service
public class DoctorServiceImpl extends ServiceImpl<DoctorMapper, Doctor> implements DoctorService {

    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 医生登录
     * @param dto
     * @return
     */
    @Override
    public Result<DoctorLoginVO> login(EmployeeLoginDto dto) {
        // 1 正常登录  用户名和密码
        // 用户名和密码都非空
        if(StringUtils.isNotBlank(dto.getUsername()) && StringUtils.isNotBlank(dto.getPassword())){
            // 1.1 根据用户名查询用户信息
            Doctor doctor = getOne(Wrappers.<Doctor>lambdaQuery().eq(Doctor::getUsername, dto.getUsername()));
            if(doctor == null){
                return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
            }
            // 1.2 比对密码  MD5加密
            String pswd = DigestUtils.md5DigestAsHex(dto.getPassword().getBytes());
            if(!pswd.equals(doctor.getPassword())){
                return Result.error(HttpCodeEnums.LOGIN_PASSWORD_ERROR);
            }
            // 1.3 返回数据  user+token
            Map<String,Object> claims = new HashMap<>();
            claims.put(JwtClaimsConstant.DOCTOR_ID, doctor.getId());
            String token = JwtUtil.createJWT(
                    jwtProperties.getDoctorSecretKey(),
                    jwtProperties.getDoctorTtl(),
                    claims);
            DoctorLoginVO doctorLoginVO = new DoctorLoginVO();
            BeanUtils.copyProperties(doctor,doctorLoginVO);
            doctorLoginVO.setToken(token);
            return Result.success(doctorLoginVO);
        }else{
            return Result.error(HttpCodeEnums.LOGIN_IS_BLANK);
        }
    }

    /**
     * 医生登出
     * @param dto
     * @return
     */
    @Override
    public Result logout(EmployeeLogoutDto dto) {
        if(StringUtils.isNotBlank(dto.getToken())){
            String token = dto.getToken();
            Claims claims = JwtUtil.parseJWT(jwtProperties.getDoctorSecretKey(),token);
            Date exp = claims.getExpiration();
            long expMillis = exp.getTime() / 1000;
            long currentTimeSeconds = System.currentTimeMillis() / 1000;
            if (expMillis < currentTimeSeconds) { // token已过期
                return Result.error(HttpCodeEnums.INVALID_TOKEN_OR_EXPIRED);
            }
            redisTemplate.opsForValue().set(token, null, (expMillis - currentTimeSeconds), TimeUnit.SECONDS);
            return Result.success();
        }else {
            return Result.error(HttpCodeEnums.INVALID_TOKEN_OR_EXPIRED);
        }
    }


    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private ClinicMapper clinicMapper;
//    /**
//     * 获取医生列表
//     * @return
//     */
//    @Override
//    public Result<Page<DoctorVO>> getList(int pageNum, int pageSize) {
//        // 创建分页对象
//        Page<Doctor> page = new Page<>(pageNum, pageSize);
//        // 执行分页查询
//        Page<Doctor> doctorPage = page(page);
//
//        return getListMethod(doctorPage);
//    }
//
//    /**
//     * 条件获取医生列表
//     * @param dto
//     * @return
//     */
//    @Override
//    public Result<Page<DoctorVO>> getListByCon(DoctorInfoDto dto, int pageNum, int pageSize) {
//        // 创建分页对象
//        Page<Doctor> page = new Page<>(pageNum, pageSize);
//        // 构建查询条件
//        LambdaQueryWrapper<Doctor> queryWrapper = Wrappers.lambdaQuery();
//        queryWrapper.eq(dto.getDepartmentId() != null, Doctor::getDepartmentId, dto.getDepartmentId())
//                .eq(dto.getClinicId() != null, Doctor::getClinicId, dto.getClinicId())
//                .like(dto.getName() != null, Doctor::getName, dto.getName());
//        // 执行分页查询
//        Page<Doctor> doctorPage = page(page, queryWrapper);
//
//        return getListMethod(doctorPage);
//    }
//
//    /**
//     * 获取医生信息封装method
//     * @param doctorPage
//     * @return
//     */
//    public Result<Page<DoctorVO>> getListMethod(Page<Doctor> doctorPage) {
//        // 获取医生列表
//        List<Doctor> doctorList = doctorPage.getRecords();
//
//        // 2 从doctorList中提取所有的departmentId
//        List<Integer> departIdList = doctorList.stream()
//                .map(Doctor::getDepartmentId)
//                .collect(Collectors.toList());
//        // 从doctorList中提取所有的clinicId
//        List<Integer> clinicIdList = doctorList.stream()
//                .map(Doctor::getClinicId)
//                .collect(Collectors.toList());
//
//        // 3 查询出 departmentList 和 clinicList
//        List<Department> departmentList = departmentMapper.selectBatchIds(departIdList);
//        List<Clinic> clinicList = clinicMapper.selectBatchIds(clinicIdList);
//
//        // 4 封装成map，提高查询性能
//        Map<Integer, String> departNameMap = departmentList.stream()
//                .collect(Collectors.toMap(Department::getId, Department::getName));
//        Map<Integer, String> clinicNameMap = clinicList.stream()
//                .collect(Collectors.toMap(Clinic::getId, Clinic::getName));
//
//        // 5 装到clinicVO中
//        List<DoctorVO> doctorVOList = new ArrayList<>();
//        for (Doctor doctor : doctorList) {
//            // 使用map集合，将O(n)降低成O(1)
//            String departmentName = departNameMap.getOrDefault(doctor.getDepartmentId(), null);
//            String clinicName = clinicNameMap.getOrDefault(doctor.getClinicId(), null);
//            doctorVOList.add(new DoctorVO(doctor, departmentName, clinicName));
//        }
//
//        // 6 将doctorVOList封装到Page对象中
//        Page<DoctorVO> doctorVOPage = new Page<>();
//        doctorVOPage.setRecords(doctorVOList);
//        doctorVOPage.setTotal(doctorPage.getTotal());
//        doctorVOPage.setSize(doctorPage.getSize());
//        doctorVOPage.setCurrent(doctorPage.getCurrent());
////        System.out.println(doctorVOPage.getTotal());
////        System.out.println(doctorVOPage.getSize());
//        return Result.success(doctorVOPage);
//    }

    /**
     * 获取医生列表
     * @return
     */
    @Override
    public Result<List<DoctorVO>> getList() {
        // 1 获取doctorList
        List<Doctor> doctorList = list();

        return getListMethod(doctorList);
    }

    /**
     * 条件获取医生列表
     * @param dto
     * @return
     */
    @Override
    public Result<List<DoctorVO>> getListByCon(DoctorInfoDto dto) {
        // 1 获取doctorList
        List<Doctor> doctorList = list(Wrappers.<Doctor>lambdaQuery()
                .eq(dto.getDepartmentId() != null, Doctor::getDepartmentId, dto.getDepartmentId())
                .eq(dto.getClinicId() != null, Doctor::getClinicId, dto.getClinicId())
                .like(dto.getName() != null,Doctor::getName,dto.getName()));

        return getListMethod(doctorList);
    }

    /**
     * 获取医生信息封装method
     * @param doctorList
     * @return
     */
    public Result<List<DoctorVO>> getListMethod(List<Doctor> doctorList){
        // 2 从doctorList中提取所有的departmentId
        List<Integer> departIdList = doctorList.stream()
                .map(Doctor::getDepartmentId)
                .collect(Collectors.toList());
        // 从doctorList中提取所有的clinicId
        List<Integer> clinicIdList = doctorList.stream()
                .map(Doctor::getClinicId)
                .collect(Collectors.toList());

        // 3 查询出 departmentList 和 clinicList
        List<Department> departmentList = departmentMapper.selectBatchIds(departIdList);
        List<Clinic> clinicList = clinicMapper.selectBatchIds(clinicIdList);

        // 4 封装成map，提高查询性能
        Map<Integer, String> departNameMap = departmentList.stream()
                .collect(Collectors.toMap(Department::getId, Department::getName));
        Map<Integer, String> clinicNameMap = clinicList.stream()
                .collect(Collectors.toMap(Clinic::getId, Clinic::getName));

        // 5 装到clinicVO中
        List<DoctorVO> doctorVOList = new ArrayList<>();
        for (Doctor doctor : doctorList){
            // 使用map集合，将O(n)降低成O(1)
            String departmentName = departNameMap.getOrDefault(doctor.getDepartmentId(),null);
            String clinicName = clinicNameMap.getOrDefault(doctor.getClinicId(),null);
            doctorVOList.add(new DoctorVO(doctor, departmentName,clinicName));
        }

        return Result.success(doctorVOList);
    }

    /**
     * 新增医生
     * @param dto
     * @return
     */
    @Override
    public Result add(DoctorInfoDto dto) {
        // 1 先校验用户名是否已存在
        List<Doctor> doctorList = list(Wrappers.<Doctor>lambdaQuery().eq(Doctor::getUsername, dto.getUsername()));
        if(!doctorList.isEmpty()){
            return Result.error(HttpCodeEnums.USERNAME_EXIST);
        }

        // 2 校验不允许空的字段
        if(StringUtils.isNotBlank(dto.getName()) &&
                StringUtils.isNotBlank(dto.getUsername()) &&
                dto.getGender() != null &&
                dto.getTitle() != null &&
                StringUtils.isNotBlank(dto.getResearchField()) &&
                dto.getDepartmentId() != null &&
                dto.getClinicId() != null ){

            Doctor doctor = new Doctor();
            BeanUtils.copyProperties(dto,doctor);
            // 3 初始化密码
            doctor.setPassword(DigestUtils.md5DigestAsHex(("12345").getBytes()));


//            System.out.println("添加头像"+dto.getAvatar());

            boolean i = save(doctor);
            if (i) {
                return Result.success();
            } else {
                return Result.error(HttpCodeEnums.SYSTEM_ERROR);
            }
        }else {
            return Result.error(HttpCodeEnums.INFO_IS_BLANK);
        }
    }

    /**
     * 修改医生信息
     * @param dto
     * @return
     */
    @Override
    public Result update(DoctorInfoDto dto) {
        // 校验不允许空的字段
        if(dto.getId() != null){
            Doctor doctor = new Doctor();
            BeanUtils.copyProperties(dto,doctor);
//            System.out.println("修改头像"+dto.getAvatar());
            boolean i = updateById(doctor);
            if (i) {
                return Result.success();
            } else {
                return Result.error(HttpCodeEnums.SYSTEM_ERROR);
            }
        }else {
            return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
        }
    }

    /**
     * 删除医生
     * @param dto
     * @return
     */
    @Override
    public Result delete(DoctorInfoDto dto) {
        // 校验不允许空的字段
        if(dto.getId() != null){
            Doctor doctor = new Doctor();
            BeanUtils.copyProperties(dto,doctor);
            boolean i = removeById(doctor);
            if (i) {
                return Result.success();
            } else {
                return Result.error(HttpCodeEnums.SYSTEM_ERROR);
            }
        }else {
            return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
        }
    }

    /**
     * 医生获取个人信息
     * @param dto
     * @return
     */
    @Override
    public Result<DoctorVO> getPersonal(DoctorInfoDto dto) {
        if(dto.getId() != null){
            Doctor one = getOne(Wrappers.<Doctor>lambdaQuery().eq(Doctor::getId, dto.getId()));
            DoctorVO doctorVO = new DoctorVO();
            BeanUtils.copyProperties(one,doctorVO);
            Department department = departmentMapper.selectById(one.getDepartmentId());
            Clinic clinic = clinicMapper.selectById(one.getClinicId());
            doctorVO.setDepartmentName(department.getName());
            doctorVO.setClinicName(clinic.getName());
            return Result.success(doctorVO);
        }else {
            return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
        }
    }

    /**
     * 医生修改密码
     * @param dto
     * @return
     */
    @Override
    public Result repass(RepassDto dto) {
        if(dto.getId() != null &&
                dto.getNewPass() != null &&
                dto.getOldPass() != null){
            Doctor one = getOne(Wrappers.<Doctor>lambdaQuery()
                    .eq(Doctor::getId, dto.getId()));
            String oldPswd = DigestUtils.md5DigestAsHex(dto.getOldPass().getBytes());

            if(oldPswd.equals(one.getPassword())){ //旧密码匹配成功
                String newPswd = DigestUtils.md5DigestAsHex(dto.getNewPass().getBytes());
                update(Wrappers.<Doctor>lambdaUpdate()
                        .eq(Doctor::getId,dto.getId())
                        .set(Doctor::getPassword,newPswd));
                return Result.success();
            }else {
                return Result.error(HttpCodeEnums.OLD_PASSWORD_WRONG);
            }
        }else {
            return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
        }
    }
}
